<?php
/**
 * Contient l'ensemble des unités d'un armée
 *
 * @version 1.0
 * @author jonathan poelen <jonathan.poelen@gmail.com>
 * @date 13-03-2010
 */
class SW_Units implements ArrayAccess, IteratorAggregate, Countable, Serializable
{
	/** @var array {group => SW_Unit, ...} : armés*/
	protected $units = array();


	/**
	 * @param array $army = null : {SW_Unit, ...}|{group => quantity, …}
	 * @param bool $isCreate = true : si false self::createUnit est appelé avant de faire self::add
	 */
	public function __construct(array $army = null, $isCreate = true)
	{
		if ($army)
		{
			if ($isCreate)
				foreach ($army as $unit)
					$this->add($unit);
			else
				foreach ($army as $g => $q)
					if ($unit = $this->createUnit($g, $q))
						$this->add($unit);
		}
	}

	/**
	 * @param mixed $group
	 * @param int $count
	 */
	public function addUnit($group, $count)
	{
		$this->units[$group]->add($count);
	}

	/**
	 * @param mixed $group
	 * @param int $count
	 */
	public function subtractUnit($group, $count)
	{
		$unit = $this->units[$group];
		$q = $unit->getCount() - $count;
		if ($q < 1)
			$this->offsetUnset($group);
		else
			$unit->setCount($q);
	}

	/**
	 * @param int $id
	 * @return int
	 */
	public function getCount($id)
	{
		return isset($this->units[$id])
			? $this->units[$id]->getCount()
			: 0;
	}

	/**
	 * @param SW_Unit $unit
	 * @return self
	 */
	public function add(SW_Unit $unit)
	{
		$this->units[$unit->getGroup()] = $unit;
		return $this;
	}

	/**
	 * @return array : {id => SW_Unit, ...}
	 */
	public function getUnits()
	{
		return $this->units;
	}

	/**
	 * @return ArrayIterator
	 */
	public function getIterator()
	{
		return new ArrayIterator($this->units);
	}

	/**
	 * @return SW_Army_Unit|null
	 */
	public function createUnit($group, $count)
	{
		return ($count > 0) ? new SW_Unit($group, $count) : null;
	}

	/**
	 * limite le nombre d'unités envoyés à ce disponible et supprimme les unités vides
	 * @param U1_Units $units
	 * @return self
	 */
	public function limitedUnits(SW_Units $units)
	{
		foreach ($this->units as $group => $unity)
		{
			if ($unity->getCount() && ($quantity = $units->getCount($group)))
				$unity->maxCount($quantity);
			else
				$this->offsetUnset($group);
		}
		return $this;
	}

	/**
	 * Assigne $value avec comme clé $offset
	 * @param int $group
	 * @param int $count
	 */
	public function offsetSet($group, $count)
	{
		if (isset($this->units[$group]))
			$this->units[$group]->setCount($count);
		else if ($unit = $this->createUnit($group, $count))
			$this->add($unit);
	}

	/**
	 * @return SW_Unit
	 */
	public function offsetGet($group)
	{
		return $this->units[$group];
	}

	/**
	 * @param mixed $group
	 * @return bool
	 */
	public function offsetExists($group)
	{
		return isset($this->units[$group]);
	}

	/**
	 * @param mixed $group
	 */
	public function offsetUnset($group)
	{
		unset($this->units[$group]);
	}

	/**
	 * @return bool
	 */
	public function isEmpty()
	{
		return empty($this->units);
	}

	/**
	 * @return array : {group_unity => count_unity, ...}
	 */
	public function toArray()
	{
		$army = array();
		foreach ($this->units as $id => $unity)
			$army[$id] = $unity->getCount();
		return $army;
	}

	public function count()
	{
		return count($this->units);
	}

	public function serialize()
	{
		return serialize($this->toArray());
	}

	public function unserialize($data)
	{
		foreach (unserialize($data) as $id => $count)
			$this->units[$id] = $this->createUnit($id, $count);
	}
}